
#include "GateMonitor.h"
#include "MySqlDB.h"
#include "md5.h"

RoomInfo::RoomInfo(int p)
{
	this->gametype = 0;
	this->ip = "";
	this->port = 0;
	this->room_id = 0;
	this->member = 0;
	this->member_limit = 0;
	this->min_chips = 0;
	this->max_chips = 0;
	this->es = NULL;
	this->is_regsiter = false;
}

RoomInfo::~RoomInfo()
{
}

void RoomInfo::set(int type,int room_id,std::string ip,int port,
		int limit_member,int min_chips,int max_chips,GateService *es)
{
	this->gametype = type;
	this->room_id = room_id;
	this->ip = ip;
	this->port = port;
	this->member_limit = limit_member;
	this->max_chips = max_chips;
	this->min_chips = min_chips;
	this->es = es;
}

int RoomInfo::cur_member(void)
{
	return this->member;
}

int RoomInfo::limit_member(void)
{
	return this->member_limit;
}

int RoomInfo::add_member(void)
{
	return (++this->member);
}

int RoomInfo::sub_member(void)
{
	return (--this->member);
}
////////////////////////////////

void GateMonitor::collection_info(void)
{

}

int GateMonitor::create_account(int svc_id,MessageBlock *mb)
{
	return 0;
//	if(NULL==mb)
//	{
//		return -1;
//	}
//
//	int sex =0;std::string account, pwd;
//	*mb >> account >> pwd >> sex;
//
//	if(sex<1 || sex>2 || account.empty()|| pwd.empty()
//			|| account.length()>100)
//	{
//		return this->respond_error_to_client(svc_id,RETURN_CREATE_ROLE,ERROR_CLIENT_INFO);
//	}
//
//	//md5 password
//	//char passwd[50] = { 0 };
//	//Md5::md5(passwd, (char*) pwd.c_str());
//
//	//create account
//	int role_id =MYSQL_INSTANCE->create_role(account,pwd,sex);
//	if(role_id<=0)
//	{
//		return this->respond_error_to_client(svc_id,RETURN_CREATE_ROLE,role_id);
//	}
//
//	return this->respond_succ_to_client(svc_id,RETURN_CREATE_ROLE);
}

int GateMonitor::log_in(int svc_id,MessageBlock *mb)
{
	MessageBlock *account_mb = NULL;
	this->msg_pool()->pop(account_mb);
	if(account_mb==NULL)
	{
		return 0;
	}
	this->player_count_++;
	mb->reset_rd_ptr();
	account_mb->write(mb->rd_ptr(),mb->data_len());
	return this->chk_account_list_->put_obj(account_mb);
}

int GateMonitor::log_out(int roleid,MessageBlock *mb)
{
	{
		LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
		GatePlayer *player = this->find_player(roleid);
		if (NULL == player)
		{
			return -1;
		}
		this->unbind_player(roleid);
		this->player_count_--;
	}
	this->exit_room(roleid);
	return this->respond_succ_to_client(roleid,RETURN_LOG_OUT);
}

int GateMonitor::enter_room(int roleid,MessageBlock *mb,bool inner)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,NULL);
	GatePlayer *player = this->find_player(roleid);
	if (NULL == player)
	{
		LOG((ERROR_LOG,"GateMonitor::enter_room-->can't find player"));
		return -1;
	}
	if(!player->is_login())
	{
		return this->respond_error_to_client(player->svc_id(),
						RETURN_ENTER_ROOM, ERROR_CLIENT_INFO);
	}
	int room_id = 0;
	if(inner==false)
	{
		*mb >> room_id;
	}
	else
	{
		room_id = player->cur_room();
	}
	RoomInfo *room = this->find_room(room_id);
	if (NULL == room)
	{
		LOG((ERROR_LOG,"GateMonitor::enter_room-->can't find room[%d]",room_id));
		return this->respond_error_to_client(player->svc_id(),
				RETURN_ENTER_ROOM, ERROR_CLIENT_INFO);
	}
	if (inner == false)
	{
		if (room->cur_member() >= room->limit_member())
		{
			return this->respond_error_to_client(player->svc_id(),
					RETURN_ENTER_ROOM, ERROR_ROOM_FULL);
		}
		player->cur_room(room_id);

		MessageBlock mb_send(1024);
		mb_send << this->gate_id() << roleid << CLIENT_ENTER_ROOM << 0
				<< room_id << player->account() << player->sex()
				<< player->dbinfo().ip
				<< player->dbinfo().port << player->dbinfo().dbname
				<< player->dbinfo().user << player->dbinfo().pwd;

		return this->dispatch_request(room_id,&mb_send);
	}

	int result = -1;
	*mb >> result;
	if(result==0)
	{
		room->add_member();
		LOG((DEBUG_LOG,"======GateMonitor::enter_room add [%d]=======",room->cur_member()));
		return this->respond_succ_to_client(player->role_id(),RETURN_ENTER_ROOM,mb);
	}
	player->cur_room(0);
	return this->respond_error_to_client(player->role_id(),RETURN_ENTER_ROOM,result,mb);
}

int GateMonitor::exit_room(int roleid,MessageBlock *mb)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,NULL);
	GatePlayer *player = this->find_player(roleid);
	if(NULL==player)
	{
		LOG((ERROR_LOG,"GateMonitor::exit_room-->can't find player"));
		return -1;
	}

	int room_id = player->cur_room();
	RoomInfo *room= this->find_room(room_id);
	if(NULL == room)
	{
		LOG((ERROR_LOG,"GateMonitor::enter_room-->can't find room[%d]",room_id));
		this->respond_error_to_client(player->role_id(),RETURN_EXIT_ROOM,ERROR_CLIENT_INFO);
		return -1;
	}
	room->sub_member();
	LOG((DEBUG_LOG,"======GateMonitor::exit_room sub[%d]=======",room->cur_member()));
	player->cur_room(0);
	MessageBlock mb_room(4096);
	this->make_up_room_info(&mb_room);
	return this->respond_succ_to_client(player->role_id(),RETURN_EXIT_ROOM,&mb_room);
}

int GateMonitor::switch_room(int roleid,MessageBlock *mb,bool inner)
{
	return 0;
//	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, NULL);
//	GatePlayer *player = this->find_player(roleid);
//	if (NULL == player)
//	{
//		LOG((ERROR_LOG,"GateMonitor::switch_room-->can't find player"));
//		return -1;
//	}
//
//	int switch_room = 0;
//	if (inner == false)
//	{
//		*mb >> switch_room;
//		player->switch_room(switch_room);
//
//		int old_room = player->cur_room();
//
//		RoomInfo *room = this->find_room(old_room);
//		if (NULL != room)
//		{
//			if (room->cur_member() >= room->limit_member())
//			{
//				return this->respond_error_to_client(roleid, RETURN_ENTER_ROOM,
//						ERROR_ROOM_FULL);
//			}
//			mb->reset_rd_ptr();
//			return this->dispatch_request(old_room, mb);
//		}
//	}
//
//	switch_room = player->switch_room();
//	//RoomInfo *room = this->eng_client_->find_room(switch_room);
//	RoomInfo *room = this->find_room(switch_room);
//	if (NULL == room)
//	{
//		LOG((ERROR_LOG,"GateMonitor::switch_room-->can't find room[%d]",switch_room));
//		return this->respond_error_to_client(roleid,
//				RETURN_SWITCH_ROOM, ERROR_CLIENT_INFO);
//	}
//	this->enter_room(roleid,mb);
//	return this->respond_succ_to_client(roleid,RETURN_SWITCH_ROOM);
}

int GateMonitor::inner_error_info(int roleid,MessageBlock *mb)
{
	LOG((ERROR_LOG,"GateMonitor::inner_error_info"));

	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,NULL);
	GatePlayer *player = this->find_player(roleid);
	if(NULL==player)
	{
		LOG((ERROR_LOG,"GateMonitor::inner_error_info-->can't find player"));
		return -1;
	}

	GateService *gs = this->find_service(player->svc_id());
	if(NULL!=gs)
	{
		this->reactor()->remove_handler(gs->get_handle(),gs);
	}
	return 0;
}

int GateMonitor::log_out(GateService *gs)
{
	if(NULL==gs)
	{
		return -1;
	}

	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, NULL);
	GatePlayer *player = this->find_player(gs->role_id());
	if (NULL == player)
	{
		return -1;
	}

	int roomid = player->cur_room();
	if (roomid == 0)
	{
		this->player_count_++;
		return this->unbind_player(gs->role_id());
	}
	MessageBlock mb(sizeof(int)*10);
	mb<<this->gate_id() << gs->role_id()<< CLIENT_LOG_OUT << 0;
	return this->dispatch_request(roomid,&mb);
}

int GateMonitor::recharge(int svc_id,MessageBlock *mb)
{
	return 0;
}

int GateMonitor::engine_register(GateService *gs,MessageBlock *mb)
{
	int game_type=0,eng_id = 0,member=0,min_chips=0,max_chips=0;
	*mb >> game_type >>eng_id >> member >> min_chips >> max_chips;
	if(game_type!=this->game_type_)
	{
		LOG((ERROR_LOG,"GateMonitor::engine_register-->[gatetype:%d][roomtype:%d][room:%d][%s:%d]",
							this->game_type_,game_type,eng_id,gs->peer_addr(),gs->peer_port()));
		gs->handle_close();
		return 0;
	}

	{
		LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, NULL);
		RoomInfo *room = this->find_room(eng_id);
		if (NULL == room)
		{
			room = new RoomInfo();
			if(NULL==room)
			{
				return 0;
			}
			room->set(this->game_type_,eng_id,gs->peer_addr(),gs->peer_port(),
					member,min_chips,max_chips,gs);

			LOG((INFO_LOG,"GateMonitor::engine_register-->[type:%d][room:%d][%s:%d]",
					game_type,eng_id,room->ip.c_str(),room->port));

			gs->set_engine();
			gs->role_id(eng_id);
			this->bind_room(eng_id, room);
		}
		else if (room->ip == gs->peer_addr()&& room->room_id == gs->role_id())
		{
			return 0;
		}
		else
		{
			LOG((ERROR_LOG,"GateMonitor::engine_register-->room [%d] exsit,old:[%s:%d]-new:[%s:%d]",
					eng_id,room->ip.c_str(),room->port,gs->peer_addr(),gs->peer_port()));
			gs->handle_close();
		}
	}
	this->send_room_info(false,eng_id);
	return 0;
}

int GateMonitor::make_up_room_info(MessageBlock *mb)
{
	if(NULL==mb)
	{
		return -1;
	}

	*mb << (int)this->engine_map_.size();
	for (EngineMap::iterator iter = this->engine_map_.begin();
			iter != this->engine_map_.end(); iter++)
	{
		RoomInfo *info = iter->second;
		if(NULL==info)
		{
			continue;
		}
		*mb << info->room_id << info->limit_member()<< info->member
				<< info->min_chips << info->max_chips;
	}
	return 0;
}

RoomInfo *GateMonitor::find_room(int room_id)
{
	EngineMap::iterator iter = this->engine_map_.find(room_id);
	if(this->engine_map_.end()==iter)
	{
		return NULL;
	}
	return iter->second;
}

int GateMonitor::bind_room(int room_id,RoomInfo *room)
{
	EngineMap::iterator iter = this->engine_map_.find(room_id);
	if(this->engine_map_.end()==iter)
	{
		this->room_change_ = true;
		this->engine_map_.insert(std::pair<int,RoomInfo*>(room_id,room));
		return 0;
	}
	return -1;
}

int GateMonitor::unbind_room(int room_id)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,NULL);
	EngineMap::iterator iter = this->engine_map_.find(room_id);
	if(this->engine_map_.end()!=iter)
	{
		this->room_change_ = true;
		DELETE(iter->second);
		this->engine_map_.erase(room_id);
		return 0;
	}
	return -1;
}

int GateMonitor::dispatch_request(int room_id,MessageBlock *mb)
{
	EngineMap::iterator iter=this->engine_map_.find(room_id);
	if(iter==this->engine_map_.end())
	{
		return -1;
	}

	GateService *gs = iter->second->es;
	if(gs==NULL)
	{
//		if(this->new_connector(room_id)!=0)
//		{
//			LOG((ERROR_LOG,"EngClientMonitor::dispatch_request-->new_connector error"));
//			return -1;
//		}
//		iter=this->room_map_.find(room_id);
//		gs = iter->second->es_;
//		if(NULL==gs)
//		{
//			return -1;
//		}
		LOG((ERROR_LOG,"EngClientMonitor::dispatch_request-->can't find room[%d]",room_id));
		return -1;
	}

	int len = mb->data_len() + sizeof(int);
	MessageBlock mb_send(len + 1);
	mb_send << len;
	mb_send.write(mb->rd_ptr(), mb->data_len());
	return gs->send_msg(&mb_send, mb_send.data_len());
}

int GateMonitor::conn_dbserver(void)
{
	std::string ip = this->cfg()["dbserver"][0u].asString();
	int port = this->cfg()["dbserver"][1u].asInt();

	if (NULL == this->dbserver_)
	{
		if (this->connector_->connect(ip, port, this->dbserver_)< 0)
		{
			LOG((ERROR_LOG,"GateMonitor::conn_dirc [%s:%d] failed",
					ip.c_str(),port));
			return -1;
		}
		this->dbserver_->set_dbesver();
	}
	return 0;
}

int GateMonitor::disconn_dbserver(void)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);
	this->dbserver_ = NULL;
	return 0;
}

int GateMonitor::conn_dircserver(void)
{
	std::string ip = this->cfg()["dircserver"][0u].asString();
	int port = this->cfg()["dircserver"][1u].asInt();

	if (NULL == this->dircserver_)
	{
		if (this->connector_->connect(ip,port, this->dircserver_)< 0)
		{
			if(this->dircserver_!=NULL)
			{
				this->dircserver_->handle_close();
				//this->unbind_service(this->dircserver_);
				this->dircserver_ = NULL;
			}
			LOG((ERROR_LOG,"GateMonitor::conn_dirc [%s:%d] failed",ip.c_str(),port));
			return -1;
		}
		this->dircserver_->set_dircsever();
	}
	return 0;
}

int GateMonitor::disconn_dircserver(void)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);
	this->register_dirc_ = false;
	this->dircserver_ = NULL;

	for (EngineMap::iterator iter = this->engine_map_.begin();
			iter != this->engine_map_.end(); iter++)
	{
		iter->second->is_regsiter = false;
	}
	return 0;
}

int GateMonitor::register_to_dirc(void)
{
	if(this->register_dirc_)
	{
		return 0;
	}
	if(this->dircserver_==NULL && this->conn_dircserver()<0)
	{
		return -1;
	}

	MessageBlock mb(256);
	mb << 0 << DIRCSERVER_LOGIN << 0
			<< this->game_type_<< this->cfg()["gamename"].asString()
			<< this->gate_id();

	mb.write_len();

	this->dircserver_->send_msg(&mb, mb.data_len());
	return 0;
}

int GateMonitor::send_room_info(bool all,int roomid)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);

	if(this->register_dirc_==false)
	{
		return 0;
	}

	int count =0;
	MessageBlock mb(4096);

	if(!all)
	{
		EngineMap::iterator iter=this->engine_map_.find(roomid);
		if(iter!=this->engine_map_.end())
		{
			RoomInfo *info = iter->second;
			if(info!=NULL)
			{
				count++;
				mb << info->room_id << info->limit_member()
						<< info->cur_member()<< info->max_chips
						<< info->min_chips;
			}
		}
	}
	else
	{
		for(EngineMap::iterator iter=this->engine_map_.begin();
				iter!=this->engine_map_.end();iter++)
		{
			RoomInfo *info = iter->second;
			if(info!=NULL && info->is_regsiter==false)
			{
				count++;
				mb << info->room_id << info->limit_member()
						<< info->cur_member()<< info->max_chips
						<< info->min_chips;
			}
		}
	}

	if(count ==0)
	{
		return 0;
	}

	if(this->dircserver_==NULL && this->conn_dircserver()<0)
	{
		return -1;
	}
	MessageBlock mb_send(4352);
	mb_send << 0 << DIRCSERVER_UPDATE<< 0
			<< this->gate_id() << this->player_count_ << count;
	mb_send.write(mb.rd_ptr(),mb.data_len());
	mb_send.write_len();

	this->dircserver_->send_msg(&mb_send, mb_send.data_len());
	return 0;
}

int GateMonitor::register_room_return(MessageBlock *mb)
{
	int size = 0, room = 0;
	*mb >> size;

	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);

	for (int i = 0; i < size; i++)
	{
		*mb >> room;
		EngineMap::iterator iter = this->engine_map_.find(room);
		if (iter != this->engine_map_.end())
		{
			LOG((INFO_LOG,"GateMonitor::register_room_return [%s:%d][room:%d] succ",
					this->dircserver_->peer_addr(),this->dircserver_->peer_port(),room));
			iter->second->is_regsiter = true;
		}
	}
	return 0;
}

int GateMonitor::process_account_chk(MessageBlock *mb)
{
	int svc_id = 0,role_id=0, cmd = 0;
	*mb >> svc_id >> role_id >>cmd;

	LOG((DEBUG_LOG,"GateMonitor::process_account_chk-->[cmd:%d][role:%d]",cmd,role_id));
	switch(cmd)
	{
		case CLIENT_LOG_IN:
		{
			return this->send_account_chk(svc_id,mb);
		}
		case RETURN_DBSERVER_PLAYER_LOGIN:
		{
			return this->recv_account_chk(svc_id,mb);
		}
		default:
			break;
	}
	return 0;
}

int GateMonitor::send_account_chk(int svc,MessageBlock *mb)
{
	int error =0,roleid_from_flash=0;
	std::string account="",passwd="";
	*mb >> error >>account >> passwd >>roleid_from_flash;

	LOG((DEBUG_LOG,"GateMonitor::send_account_chk-->[%s][%d]",account.c_str(),roleid_from_flash));

	GateService *gs =this->find_service(svc);
	if (NULL==gs)
	{
		LOG((ERROR_LOG,"GateMonitor::send_account_chk-->can't find svc"));
		return 0;
	}

	if(account.empty() || passwd.empty() || roleid_from_flash<=0)
	{
		return this->respond_error_to_client(gs->unique_id(),RETURN_LOG_IN,ERROR_CLIENT_INFO);
	}

	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
	GatePlayer *player = this->find_player(roleid_from_flash);
	if (NULL != player)
	{
		LOG((ERROR_LOG,"GateMonitor::send_account_chk-->player exist[%s][%d]",account.c_str(),roleid_from_flash));
		return 0;
	}
	gs->role_id(roleid_from_flash);

	this->player_pool_.pop(player);
	if(NULL==player)
	{
		LOG((ERROR_LOG,"GateMonitor::process_account_chk-->player pool error"));
		return -1;
	}
	player->monitor(this);
	player->account(account);
	player->role_id(roleid_from_flash);
	player->svc_id(gs->unique_id());
	this->bind_player(roleid_from_flash,player);

	MessageBlock mb_send(512);
	mb_send <<0 << DBSERVER_PLAYER_LOGIN<< 0
			<< account << passwd << roleid_from_flash;
	mb_send.write_len();

	if(this->send_to_dbserver(&mb_send)<0)
	{
		LOG((ERROR_LOG,"GateMonitor::send_account_chk-->send error[%s][%d]",account.c_str(),roleid_from_flash));
		return this->respond_error_to_client(gs->unique_id(),
				RETURN_LOG_IN,ERROR_CLIENT_INFO);
	}
	return 0;
}

int GateMonitor::recv_account_chk(int svc,MessageBlock *mb)
{
	int error =0,roleid=0,dbport=0,sex = 0,chips=0;
	std::string account="",dbname="",user="",pwd="",dbip="";
	*mb >> error >> roleid >> account >> sex >>chips >> dbip
		>> dbport >> dbname >>user>> pwd;

	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
	GatePlayer *player = this->find_player(roleid);
	LOG((INFO_LOG,"GateMonitor::recv_account_chk-->[%d][%s][%s:%d][error:%d]",
			roleid,account.c_str(),dbip.c_str(),dbport,error));
	if(error!=0)
	{
		if (NULL != player)
		{
			this->respond_error_to_client(player->svc_id(), RETURN_LOG_IN,error);
			return this->unbind_player(player->role_id());
		}
		return 0;
	}
	player->login(true);
	player->sex(sex);
	player->chips(chips);
	player->dbinfo().set(dbip,dbport,dbname,user,pwd);
	return this->respond_succ_to_client(player->role_id(),RETURN_LOG_IN);
}

int GateMonitor::send_to_dbserver(MessageBlock *mb)
{
	if(NULL==this->dbserver_ && this->conn_dbserver()<0)
	{
		LOG((ERROR_LOG,"GateMonitor::send_to_dbserver connect dbserver failed"));
		return -1;
	}
	return this->dbserver_->send_msg(mb,mb->data_len());
}
